<?php
/**
 * Smarty plugin
 * @package Smarty
 * @subpackage plugins
 */

/**
 * Smarty {defun} compiler block function plugin
 *
 * Type:     compiler block function<br>
 * Name:     defun<br>
 * Purpose:  parse a tree-array recursively
 * @link http://www.phpinsider.com/smarty-forum/viewtopic.php?t=291
 *       (Smarty discussion forums)
 * @param string containing var-attribute and value-attribute
 * @param Smarty_Compiler
 */

/* create code for a function call */
function smarty_compiler_fun($tag_args, &$compiler)	{
	$_attrs=$compiler->_parse_attrs($tag_args);
	if (!isset($_attrs['name']))
		$compiler->_syntax_error("fun: missing name parameter");
	$_func_name=$compiler->_dequote($_attrs['name']);
	$_func='smarty_fun_'.$_func_name;
	$_params='array(';
	$_sep='';
	unset($_attrs['name']);
	foreach ($_attrs as $_key=>$_value) {
		$_params.="$_sep'$_key'=>$_value";
		$_sep=',';
		}
	$_params.=')';
	return "$_func(\$this, $_params); ";

}
$this->register_compiler_function('fun', 'smarty_compiler_fun');


/* create code for a function declaration */
function smarty_compiler_defun($tag_args, &$compiler) {
	$attrs=$compiler->_parse_attrs($tag_args);
	$func_key='"' . md5('php-5') . '[[' . md5(uniqid('sucks')) . '";';
	array_push($compiler->_tag_stack, array('defun', $attrs, $tag_args, $func_key));
	if (!isset($attrs['name'])) $compiler->_syntax_error("defun: missing name parameter");

	$func_name=$compiler->_dequote($attrs['name']);
	$func='smarty_fun_'.$func_name;
	return $func_key . "if (!function_exists('$func')) { function $func(&\$this, \$params) { \$_fun_tpl_vars=\$this->_tpl_vars; \$this->assign(\$params); ";
}


/* create code for closing a function definition and calling said function */
function smarty_compiler_defun_close($tag_args, &$compiler) {
	list($name, $attrs, $open_tag_args, $func_key)=array_pop($compiler->_tag_stack);
	if ($name!='defun') $compiler->_syntax_error("unexpected {/defun}");
	return " \$this->_tpl_vars=\$_fun_tpl_vars; }} " . $func_key . smarty_compiler_fun($open_tag_args, $compiler);
}
$this->register_compiler_function('/defun', 'smarty_compiler_defun_close');


/* callback: replace all $this with $smarty */
function smarty_replace_fun($match) {
	$tokens=token_get_all('<?php ' . $match[2]);
	array_shift($tokens);
	for ($i=0, $count=count($tokens); $i<$count; $i++) {
		if (is_array($tokens[$i])) {
			if ($tokens[$i][0] == T_VARIABLE && $tokens[$i][1] == '$this') {
				$tokens[$i]='$smarty';
			} else {
				$tokens[$i]=$tokens[$i][1];
			}
		}
	}
	return implode('', $tokens);
}


/* postfilter to squeeze the code to make php5 happy */
function smarty_postfilter_defun($source, &$compiler) {
	$search='("' . md5('php-5') . '\[\[[0-9a-f]{32}";)';
	if ((double)phpversion()>=5.0) {
		/* filter sourcecode. look for func_keys and replace all $this
		   in-between with $smarty */
		while (1) {
			$new_source=preg_replace_callback('/' . $search . '(.*)\\1/Us', 'smarty_replace_fun', $source);
			if (strcmp($new_source, $source)==0) break;
			$source=$new_source;
		}
	} else {
		/* remove func_keys */
		$source=preg_replace('/' . $search . '/', '', $source);
	}
	return $source;
}
$this->register_postfilter('smarty_postfilter_defun');


?>